package com.sleepingcat.ft_flutter.fragment

import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.os.Parcelable
import android.view.View
import android.view.ViewGroup
import android.view.Window
import androidx.activity.addCallback
import androidx.fragment.app.setFragmentResult
import androidx.navigation.fragment.findNavController
import com.cat.android.lib_base.base.IRouterFragment
import com.cat.android.lib_base.base.RouterActivity
import com.cat.android.lib_base.base.RouterFragmentImpl
import com.idlefish.flutterboost.FlutterBoost
import com.idlefish.flutterboost.FlutterBoostUtils
import com.idlefish.flutterboost.containers.FlutterActivityLaunchConfigs
import com.idlefish.flutterboost.containers.FlutterBoostFragment
import io.flutter.embedding.android.RenderMode
import io.flutter.embedding.android.TransparencyMode
import java.io.Serializable

/**
 * @作者 志浩
 * @时间 2025/2/28 23:05
 * @描述 TODO
 */
class MyFlutterFragment : FlutterBoostFragment(), IRouterFragment by RouterFragmentImpl() {
    private val TAG = "FlutterFragment"
    lateinit var mActivity: RouterActivity<*>

    companion object {
        private const val ARG_REQUEST_CODE = "ARG_REQUEST_CODE"
        fun build(uniqueId: String?, url: String?, urlParams: Map<String, Any>?, opaque: Boolean = true): MyFlutterFragment {
            return CachedEngineFragmentBuilder(MyFlutterFragment::class.java)
                .destroyEngineWithFragment(false)
                .uniqueId(uniqueId)
                .transparencyMode(if (opaque) TransparencyMode.opaque else TransparencyMode.transparent)
                .url(url)
                .urlParams(urlParams)
                .build()
        }

        fun createArgument(uniqueId: String?, url: String, requestCode: String?, urlParams: HashMap<String, Any>?, opaque: Boolean = true): Bundle {
            val args = Bundle()
            args.putString(ARG_CACHED_ENGINE_ID, FlutterBoost.ENGINE_ID)
            args.putString(ARG_REQUEST_CODE, requestCode)
            args.putBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, false)
            args.putString(ARG_FLUTTERVIEW_RENDER_MODE, RenderMode.surface.name)
            args.putString(ARG_FLUTTERVIEW_TRANSPARENCY_MODE, if (opaque) TransparencyMode.opaque.name else TransparencyMode.transparent.name)
            args.putBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, true)
            args.putString(FlutterActivityLaunchConfigs.EXTRA_URL, url)
            args.putSerializable(FlutterActivityLaunchConfigs.EXTRA_URL_PARAM, urlParams)
            args.putString(FlutterActivityLaunchConfigs.EXTRA_UNIQUE_ID, uniqueId ?: FlutterBoostUtils.createUniqueId(url))
            return args
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initFragment(this)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        if (!isOpaque) {
            for (i in 0 until (view as ViewGroup).childCount) {
                view.getChildAt(i).setBackgroundColor(Color.TRANSPARENT)
            }
            view.setBackgroundColor(Color.TRANSPARENT)
            requireActivity().window.apply {
                setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(this) {
            onBackPressed()
        }
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is RouterActivity<*>){
            mActivity = context
            initRouterActivity(mActivity)
        }
    }

    override fun finishContainer(result: MutableMap<String, Any>?) {
        try {
            val navController = findNavController()
            val isTopLevel = navController.currentDestination?.id == navController.graph.startDestinationId
            if (isTopLevel) {
                super.finishContainer(result)
            } else {
                val requestCode = arguments?.getString(ARG_REQUEST_CODE)
                if (requestCode != null && result != null) {
                    val bundle = Bundle()
                    result.forEach { (t, u) ->
                        when (u) {
                            is String -> bundle.putString(t, u)
                            is Int -> bundle.putInt(t, u)
                            is Boolean -> bundle.putBoolean(t, u)
                            is Double -> bundle.putDouble(t, u)
                            is Float -> bundle.putFloat(t, u)
                            is Serializable -> bundle.putSerializable(t, u)
                            is Parcelable -> bundle.putParcelable(t, u)
                        }
                    }
                    setFragmentResult(requestCode, bundle)
                }
                onFinishContainer()
            }
        } catch (e: Exception) {
            // 如果是原生启动flutter的dialog，且告诉flutter端需要创建activity容器时，此时就会走回MyFlutterActivity那套流程
            // 那套流程是没有用到navigation，所以是找不到这个navigator，所以会报错，此时就要他走原来的逻辑
            super.finishContainer(result)
        }
    }

    /**
     * 返回页面时，如果是通过侧滑返回，则会调用flutterBoostFragment的onBackPress，里面会把结果通过getActivity().setResult(Activity.RESULT_OK, intent)把结果返回出去
     * 返回完后点调用这个onFinishContainer销毁页面，默认是退出该fragment的activity
     *
     * 另外如果在flutter端使用boost的pop方法，内部逻辑其实是找到这个container，然后调用finishContainer(参数是flutter返回的)，代码看FlutterBoostPlugin
     * 这里的container其实就是对应MyFlutterFragment，
     *
     * 记住，有两种情况container是有uniqueId，
     * 一种是原生这边启动一个flutter页面，就算我们不传，他也会根据url自动生成
     * 一种是flutter页面启动一个原生页面，如withContainer=true，
     */
    override fun onFinishContainer() {
        try {
            val navController = findNavController()
            val isTopLevel = navController.currentDestination?.id == navController.graph.startDestinationId
            if (!isTopLevel) {
                navController.popBackStack()
            } else {
                super.onFinishContainer()
            }
        } catch (e: Exception) {
            super.onFinishContainer()
        }
    }

}